home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 43.zip / Sources C- WorkDisk V.adf / iff / jiff-hires.c next >
C/C++ Source or Header  |  1987-02-15  |  9KB  |  393 lines

  1.  
  2. /**********************************************************************
  3. *
  4. *            jiff.c   Jim Kent's iff - ilbm  reader
  5. *
  6. * This is the (sortof) short (sortof) simple no-frills IFF reader
  7. * to get something out of DPaint, Images, or the Animator.  It
  8. * works well with the Aztec C compiler.  It should work with Lattice
  9. * but you never know until you try it.  I haven't.
  10. *
  11. * I've included a simple main program.  This is just to make it
  12. * stand alone.  Since amiga screen initializations are massive, all
  13. * it does as is is read it into a BitMap, and then free up the BitMap.
  14. * Should crash it if it's gonna crash though.
  15. *
  16. * The main interface to this is through the routine read_iff(filename).
  17. * This returns a ILBM_info structure-pointer on success, and NULL on
  18. * failure.  It cleans up after itself on failure.
  19. *
  20. * I hope you will find this useful and easy to use.  Please forgive
  21. * my funky indentation style?  Well at least I'm consistent!
  22. *
  23. * To demonstrate what a nice guy I am even though I'm far from wild
  24. * about the IFF standard I'm placing this in the public domain.  When
  25. * you remove the DEBUG and PARANOID definitions the code is only
  26. * 1536 bytes long.
  27. *
  28. *        -Jim Kent  April 22, 1986
  29. ************************************************************************/
  30.  
  31. #include <stdio.h>
  32. #include <exec/types.h>
  33. #include <exec/memory.h>
  34. #include <graphics/gfx.h>
  35. #include <libraries/dos.h>
  36. #include "df1:iff/jiff-hires.h"
  37.  
  38. /*this is an all too common state of software development.  Get rid
  39.   of this define as soon as it runs*/
  40. /* #define DEBUG */
  41.  
  42. /*this is the normal state of software development.  Seriously undefine
  43.   this to make it shut up about errors and reduce code size half way
  44.   through beta testing... */
  45. /* #define PARANOID */
  46.  
  47.  
  48. static struct ILBM_info *read_ilbm(), *read_body();
  49.  
  50. /* OK this code is almost re-entrant.  Pass this guy from above to
  51.    make it really re-entrant.  (Why do you need a reentrant ILBM
  52.    reader though??  Maybe for Dale ... ) */
  53. static struct ILBM_info root_info;  /*static so get initialized to zero*/
  54.  
  55.  
  56. #ifdef PARANOID
  57. /* a little paranoid routine that say's where we got before EOF */
  58. static void
  59. iff_truncated(where)
  60. int where;
  61. {
  62. printf("ILBM truncated %d\n", where);
  63. free_planes(&root_info.bitmap);
  64. }
  65. #endif PARANOID
  66.  
  67.  
  68. struct ILBM_info *
  69. read_iff(name, just_colors)
  70. char *name;
  71. short just_colors;
  72. {
  73. struct ILBM_info *info = &root_info;
  74. FILE *file;
  75. struct form_chunk chunk;
  76.  
  77. if ((file = fopen(name, "r") ) == 0)
  78.     {
  79. #ifdef PARANOID
  80.     printf("couldn't Open %s to read\n", name);
  81. #endif PARANOID
  82.     return(NULL);
  83.     }
  84.  
  85. if ( fread(&chunk, sizeof(struct form_chunk), 1, file) != 1)
  86.     {
  87. #ifdef PARANOID
  88.     iff_truncated(0);
  89. #endif PARANOID
  90.     fclose(file);
  91.     return(NULL);
  92.     }
  93.  
  94. if (chunk.fc_type.b4_type != FORM)
  95.     {
  96. #ifdef PARANOID
  97.     printf("not a FORM - %s\n", name);
  98. #endif PARANOID
  99.     fclose(file);
  100.     return(NULL);
  101.     }
  102.  
  103. if (chunk.fc_subtype.b4_type != ILBM)
  104.     {
  105. #ifdef PARANOID
  106.     printf("FORM not an ILBM - %s\n", name);
  107. #endif PARANOID
  108.     fclose(file);
  109.     return(NULL);
  110.     }
  111.  
  112. #ifdef DEBUG
  113. printf("FORM %ld ILBM\n", chunk.fc_length);
  114. #endif DEBUG
  115.  
  116. info = read_ilbm(file, info, chunk.fc_length - sizeof(chunk), just_colors);
  117. fclose(file);
  118. #ifdef PARANOID
  119. printf("info = %lx\n", info);
  120. #endif PARANOID
  121. return(info);
  122. }
  123.  
  124. static
  125. struct ILBM_info *
  126. read_ilbm(file, info, length, just_colors)
  127. FILE *file;
  128. struct ILBM_info *info;
  129. long length;
  130. short just_colors;
  131. {
  132. struct iff_chunk chunk;
  133. int i;
  134. long read_in = 0;
  135. int got_header = FALSE;  /*to make sure gots the header first*/
  136. int got_cmap = FALSE;  /*make sure get cmap before "BODY" */
  137.  
  138. /*make sure the Planes are all NULL so can free up memory easily
  139.   on error abort */
  140. for (i=0; i<8; i++)
  141.     info->bitmap.Planes[i] = NULL;
  142.  
  143. while (read_in < length)
  144.     {
  145.     if (fread(&chunk, sizeof(chunk), 1, file) != 1)
  146.         {
  147. #ifdef PARANOID
  148.         iff_truncated(1);
  149. #endif PARANOID
  150.         return(NULL);
  151.         }
  152.     switch (chunk.iff_type.b4_type)
  153.         {
  154.         case BMHD:
  155. #ifdef DEBUG
  156.             printf("\tBMHD %ld\n", chunk.iff_length);
  157. #endif DEBUG
  158.             if (fread(&info->header, sizeof(info->header), 1, file) != 1)
  159.                 {
  160. #ifdef PARANOID
  161.                 iff_truncated(2);
  162. #endif PARANOID
  163.                 return(NULL);
  164.                 }
  165.             got_header = TRUE;
  166.             break;
  167.         case CMAP:
  168. #ifdef DEBUG
  169.             printf("\tCMAP %ld\n", chunk.iff_length);
  170. #endif DEBUG
  171.             if (!got_header)
  172.                 {
  173. #ifdef PARANOID
  174.                 printf("CMAP befor BMHD\n");
  175. #endif PARANOID
  176.                 return(NULL);
  177.                 }
  178.             if (chunk.iff_length <= 3*MAXCOL )
  179.                 {
  180.                 if (fread(info->cmap, (int)chunk.iff_length, 1, file) != 1)
  181.                     {
  182. #ifdef PARANOID
  183.                     iff_truncated(3);
  184. #endif PARANOID
  185.                     return(NULL);
  186.                     }
  187.                 }
  188.             else
  189.                 {
  190. #ifdef PARANOID
  191.                 printf("warning, more than %d colors in ILBM CMAP\n",
  192.                     MAXCOL);
  193. #endif PARANOID
  194.                 if (fread(info->cmap, 3*MAXCOL, 1, file) != 1)
  195.                     {
  196. #ifdef PARANOID
  197.                     iff_truncated(4);
  198. #endif PARANOID
  199.                     return(NULL);
  200.                     }
  201.                 bit_bucket(file, chunk.iff_length - sizeof(3*MAXCOL));
  202.                 }
  203.             got_cmap = TRUE;
  204.             if (just_colors)
  205.                 return(info);
  206.             break;
  207.         case BODY:
  208.             if (!got_cmap)
  209.                 {
  210. #ifdef PARANOID
  211.                 printf("BODY before CMAP\n");
  212. #endif PARANOID
  213.                 return(NULL);
  214.                 }
  215. #ifdef DEBUG
  216.             printf("\tBODY %ld\n", chunk.iff_length);
  217. #endif DEBUG
  218.             return( read_body(file, info, chunk.iff_length) );
  219.  
  220.         default:    /*squawk about unknown types if PARANOID */
  221. #ifdef PARANOID
  222.             printf("\t unknown type %lx of b4_type\n", chunk.iff_type.b4_type);
  223. #endif PARANOID
  224.         case GRAB:  /*ignore documented but unwanted types*/
  225.         case DEST:
  226.         case SPRT:
  227.         case CAMG:
  228.         case CRNG:
  229.         case CCRT:
  230.             bit_bucket(file, chunk.iff_length);
  231.             break;
  232.         }
  233.     read_in += chunk.iff_length + sizeof(chunk);
  234.     }
  235. #ifdef PARANOID
  236. printf("no BODY in ILBM\n");
  237. #endif PARANOID
  238. return(NULL); 
  239. }
  240.  
  241.  
  242.  
  243. static
  244. struct ILBM_info *
  245. read_body(file, info, length)
  246. FILE *file;
  247. register struct ILBM_info *info;
  248. long length;
  249. {
  250. struct ILBM_header *header;
  251. struct BitMap *bm;
  252. int i, j;
  253. int rlength;
  254. int plane_offset;
  255.  
  256. #ifdef DEBUG
  257. printf("read_body( %lx %lx %ld)\n", file, info, length);
  258. #endif DEBUG
  259.  
  260. #ifdef PARANOID
  261. /* when paranoid do a little error checking first ... fail fast! */
  262. if (info->header.nPlanes > 8)
  263.     {
  264.     printf("Whoa, woe  Dale only speaks 8 planes boy, not %d\n",
  265.         info->header.nPlanes);
  266.     return(NULL);
  267.     }
  268. #endif PARANOID
  269.  
  270. /* ok a little more error checking */
  271. if (info->header.compression != 0 && info->header.compression != 1)
  272.     {
  273. #ifdef PARANOID
  274.     printf("unrecognized compression type %d\n", info->header.compression);
  275. #endif PARANOID
  276.     return(NULL);
  277.     }
  278.  
  279. /*set up the bitmap part that doesn't involve memory allocation first -
  280.   hey this part does get done, and let's be optimistic...*/
  281. info->bitmap.BytesPerRow = line_bytes(info->header.w);
  282. info->bitmap.Rows = info->header.h;
  283. info->bitmap.Depth = info->header.nPlanes;
  284. info->bitmap.Flags = info->bitmap.pad = 0;
  285.  
  286. rlength = info->bitmap.Rows * info->bitmap.BytesPerRow;
  287.  
  288. for (i=0; i<info->header.nPlanes; i++)
  289.     {
  290.     if ((info->bitmap.Planes[i] = ralloc(rlength)) == NULL)
  291.         {
  292. #ifdef PARANOID
  293.         printf("couldn't alloc plane %d in read_body\n",i);
  294. #endif PARANOID
  295.         free_planes( &info->bitmap );
  296.         return(NULL);
  297.         }
  298.     }
  299. plane_offset = 0;
  300. for (i=0; i<info->bitmap.Rows; i++)
  301.     {
  302.     /* this test should be in the inner loop for shortest code,
  303.        in the outer loop for greatest speed, so sue me I compromised */
  304.     if (info->header.compression == 0)
  305.         {
  306.         for (j = 0; j < info->bitmap.Depth; j++)
  307.             {
  308.             if ( fread(info->bitmap.Planes[j] + plane_offset,
  309.                 info->bitmap.BytesPerRow, 1, file) != 1)
  310.                 {
  311. #ifdef PARANOID
  312.                 iff_truncated(6);
  313. #endif PARANOID
  314.                 free_planes( &info->bitmap);
  315.                 return(NULL);
  316.                 }
  317.             }
  318.         }
  319.     else
  320.         {
  321.         register char *dest, value;
  322.         register int so_far, count;  /*how much have unpacked so far*/
  323.  
  324.         for (j = 0; j < info->bitmap.Depth; j++)
  325.             {
  326.             so_far = info->bitmap.BytesPerRow;
  327.             dest = (char *)info->bitmap.Planes[j] + plane_offset;
  328.             while (so_far > 0)
  329.                 {
  330.                 if ( (value = getc(file)) == 128)
  331.                     {
  332. #ifdef DEBUG
  333.                     printf("NOP\n");
  334. #endif DEBUG
  335.                     }
  336.                 else if (value > 0)
  337.                     {
  338.                     count = (int)value + 1;
  339.                     so_far -= count;
  340.                     if ( fread(dest, count, 1, file) != 1)
  341.                         {
  342. #ifdef PARANOID
  343.                         iff_truncated(7);
  344. #endif PARANOID
  345.                         free_planes( &info->bitmap);
  346.                         return(NULL);
  347.                         }
  348.                     dest += count;
  349.                     }
  350.                 else 
  351.                     {
  352.                     count = (int)-value + 1;
  353.                     so_far -= count;
  354.                     value = getc(file);
  355.                     while (--count >= 0)  /*this is fastest loop in C */
  356.                         *dest++ = value;
  357.                     }
  358.                 }
  359.             if (so_far != 0)
  360.                 {
  361. #ifdef PARANOID
  362.                 printf("compression quite screwed up, aborting %d\n", so_far);
  363. #endif PARANOID
  364.                 free_planes( &info->bitmap);
  365.                 return(NULL);
  366.                 }
  367.             }
  368.         }
  369.     plane_offset += info->bitmap.BytesPerRow;
  370.     }
  371. return(info);
  372. }
  373.  
  374.  
  375. void
  376. free_planes(bmap)
  377. register struct BitMap *bmap;
  378. {
  379. PLANEPTR plane;
  380. long length;
  381. short i;
  382.  
  383. length = bmap->BytesPerRow * bmap->Rows;
  384.  
  385. for (i=0; i<8; i++)
  386.     if ( (plane = bmap->Planes[i]) != NULL)
  387.         rfree(plane, length);
  388. }
  389.  
  390.  
  391.  
  392.  
  393.